home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Overview / Sample / SampleMisc.a < prev    next >
Encoding:
Text File  |  1994-11-18  |  33.8 KB  |  908 lines  |  [TEXT/MPS ]

  1. *
  2. *    Apple Macintosh Developer Technical Support
  3. *
  4. *    MultiFinder-Aware Simple Sample Application
  5. *
  6. *    Sample
  7. *
  8. *    SampleMisc.a    -    Assembler Source
  9. *
  10. *    Copyright © 1989 Apple Computer, Inc.
  11. *    All rights reserved.
  12. *
  13. *    Versions:    
  14. *        1.00            08/88
  15. *        1.01            11/88
  16. *        1.02            04/89
  17. *        1.03            06/89
  18. *        1.04            06/92
  19. *
  20. *    Components:
  21. *        Sample.p        June 1, 1989
  22. *        Sample.c        June 1, 1989
  23. *        SampleInit.c        June 2, 1992
  24. *        Sample.a        June 1, 1989
  25. *        Sample.inc1.a        June 1, 1989
  26. *        SampleMisc.a        June 1, 1989
  27. *        Sample.r        June 1, 1989
  28. *        Sample.h        June 1, 1989
  29. *        PSample.make        June 1, 1989
  30. *        CSample.make        June 1, 1989
  31. *        ASample.make        June 1, 1989
  32. *        CSample.π        June 2, 1992
  33. *        CSample.π.rsrc        June 2, 1992
  34. *
  35. *    Sample is an example application that demonstrates how to
  36. *    initialize the commonly used toolbox managers, operate 
  37. *    successfully under MultiFinder, handle desk accessories, 
  38. *    and create, grow, and zoom windows.
  39. *
  40. *    It does not by any means demonstrate all the techniques 
  41. *    you need for a large application. In particular, Sample 
  42. *    does not cover exception handling, multiple windows/documents, 
  43. *    sophisticated memory management, printing, or undo. All of 
  44. *    these are vital parts of a normal full-sized application.
  45. *
  46. *    This application is an example of the form of a Macintosh 
  47. *    application; it is NOT a template. It is NOT intended to be 
  48. *    used as a foundation for the next world-class, best-selling, 
  49. *    600K application. A stick figure drawing of the human body may 
  50. *    be a good example of the form for a painting, but that does not 
  51. *    mean it should be used as the basis for the next Mona Lisa.
  52. *
  53. *    We recommend that you review this program or TESample before 
  54. *    beginning a new application.
  55.  
  56. * ================================================
  57. * -------------- INCLUDES SECTION ----------------
  58. * ================================================
  59.  
  60.     PRINT    PUSH,OFF            ; don't print any of this stuff
  61.  
  62.     INCLUDE    'ToolEqu.a'
  63.     INCLUDE    'Traps.a'
  64.     INCLUDE    'PackMacs.a'
  65.     INCLUDE    'QuickEqu.a'
  66.     INCLUDE    'SysEqu.a'
  67.     INCLUDE    'Sample.inc1.a'            ; all our macros and data templates
  68.  
  69.     PRINT    POP                ; restore the PRINT options
  70.  
  71.  
  72. * ================================================
  73. * -----------  DATA STORAGE USAGE  ---------------
  74. * ================================================
  75. * Here we will IMPORT the data that is being from the
  76. * DATA STORAGE ALLOCATION section of ASample.a.  By IMPORTing them
  77. * at this point, they will be accessible by this entire source file.
  78. * The symbol is IMPORTed and associated with the original template
  79. * as defined in the ASample.inc1.a file.  This allows us to use
  80. * the identifiers in the template.
  81.  
  82.         IMPORT    QD:QDGlobals
  83.         IMPORT    G:AppGlobals
  84.  
  85.  
  86. * ================================================
  87. * FUNCTION TrapAvailable(tNumber: INTEGER): BOOLEAN;
  88. * ================================================
  89. * Check to see if a given trap is implemented. This is only used by the
  90. * Initialize routine in this program, so we put it in the Initialize segment.
  91. * The recommended approach to see if a trap is implemented is to see if
  92. * the address of the trap routine is the same as the address of the
  93. * Unimplemented trap. Needs to be called after call to _SysEnvirons so that it can
  94. * check if a ToolTrap is out of range of a pre-Mac II ROM.  This routine
  95. * assumes we're running on 128k ROMs. It also requires the entire trap
  96. * word so that it knows if it is a ToolTrap or an OSTrap.
  97.  
  98.         SEG    'Initialize'        ; case sensitive
  99. TrapAvailable    FUNC    EXPORT            ; any source file can use this routine
  100.  
  101. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  102. Result        DS.W    1            ; function's result returned to caller
  103. ParamBegin    EQU    *            ; start parameters after this point
  104. tNumber        DS.W    1            ; the trap number passed by caller
  105. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  106. RetAddr     DS.L    1            ; place holder for return address
  107. A6Link        DS.L    1            ; place holder for A6 link
  108. TrapAddress    DS.L    1            ; local copy of trap address
  109. LocalSize    EQU     *            ; size of all the local variables
  110.         ENDR
  111.  
  112.         WITH    StackFrame        ; cover our local stack frame
  113.         LINK    A6,#LocalSize        ; allocate our local stack frame
  114.  
  115.         MOVE.W    #False,Result(A6)    ; initialize function's result
  116.  
  117.         MOVE.W    tNumber(A6),D0        ; get trap word into D0
  118.         BTST    #ToolTrapBit,D0        ; test if number is Tool trap
  119.         BEQ.S    GetOSTrap        ; off means a new OS trap number
  120.         
  121.         MOVE.W    G.Mac.machineType,D1    ; get the machine type we're running
  122.         CMPI.W    #envMachUnknown,D1    ; are we on a future machine?
  123.         BEQ.S    GetToolTrap        ; yes, go ahead and test for a new Tool trap
  124.         
  125.         CMPI.W    #envMacII,D1        ; are we on a Mac II or better?
  126.         BGE.S    GetToolTrap        ; yes, go ahead and test for a new Tool trap
  127.  
  128. * ------------- TEST FOR EXCEEDING TRAP TABLE -------------
  129. * At this point we know we're on a Mac 512E, Plus, or SE and need to
  130. * test the trap number for being in the range of < $0200
  131.  
  132.         AND.W    #$03FF,D0        ; mask off the ToolTrap bits
  133.         CMPI.W    #$01FF,D0        ; is this trap in our trap table?
  134.         BLE.S    GetToolTrap        ; yes, go ahead and test for a new Tool trap
  135.         BRA.S    Exit            ; no, then this trap cannot be present
  136.         
  137. * ------------- TEST FOR NEW TOOL TRAP -------------
  138.  
  139. GetToolTrap    _GetTrapAddress ,NewTool    ; NewTool trap macro, trap is in D0
  140.         MOVE.L    A0,TrapAddress(A6)    ; save a copy of the trap address
  141.         BRA.S    TestUnimp        ; test against Unimplemented trap
  142.         
  143. * ------------- TEST FOR NEW OS TRAP -------------
  144.  
  145. GetOSTrap    _GetTrapAddress ,NewOS        ; NewOS trap macro, trap is in D0
  146.         MOVE.L    A0,TrapAddress(A6)    ; save a copy of the trap address
  147. TestUnimp    MOVE.W    #Unimplemented,D0    ; get address of Unimplemented trap
  148.         _GetTrapAddress
  149.         CMPA.L    TrapAddress(A6),A0    ; see if trap is implemented
  150.         BEQ.S    Exit            ; nope, they're the same
  151.         MOVE.W    #True,Result(A6)    ; yes, we've got the trap
  152.  
  153. Exit        UNLK    A6            ; destroy the link
  154.         MOVEA.L    (SP)+,A0        ; pull off the return address
  155.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  156.         JMP    (A0)            ; return to the caller
  157.  
  158.         DbgInfo    TrapAval        ; this name will appear in the debugger
  159.         ENDF
  160.  
  161. * ================================================
  162. * FUNCTION GoGetRect(rectID: INTEGER; VAR theRect: Rect) : BOOLEAN;
  163. * ================================================
  164. * This utility loads the global rectangles that are used by the window
  165. * drawing routines. It shows how the resource manager can be used to hold
  166. * values in a convenient manner. These values are then easily altered without
  167. * having to re-compile the source code. GoGetRect will return a BOOLEAN that
  168. * indicates if it was successful in getting the rectangle.
  169.  
  170. * A0 is being used for resource handle.
  171.  
  172.         SEG    'Initialize'        ; case sensitive
  173. GoGetRect    FUNC    EXPORT            ; any source file can use this routine
  174.  
  175. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  176. Result        DS.W    1            ; function's result returned to caller
  177. ParamBegin    EQU    *            ; start parameters after this point
  178. RectID        DS.W    1            ; resource ID of rect passed by caller
  179. TheRect        DS.L    1            ; the rect's pointer passed by caller
  180. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  181. RetAddr     DS.L    1            ; place holder for return address
  182. A6Link        DS.L    1            ; place holder for A6 link
  183. LocalSize    EQU     *            ; size of all the local variables
  184.         ENDR
  185.  
  186.         WITH    StackFrame        ; cover our local stack frame
  187.         LINK    A6,#LocalSize        ; allocate our local stack frame
  188.  
  189.         MOVE.W    #False,Result(A6)    ; initialize function's result
  190.  
  191.         CLR.L    -(SP)            ; create space for result
  192.         MOVE.L    #'RECT',-(SP)
  193.         MOVE.W    RectID(A6),-(SP)    ; get the stop light's rect
  194.         _GetResource
  195.         MOVEA.L    (SP)+,A0        ; handle to RECT resource in A0
  196.         CMPA.L    #NIL,A0            ; test for NIL handle
  197.         BEQ.S    Exit            ; didn't get resource, exit this procedure
  198.  
  199.  
  200. * -------- COPY THE RESOURCE TO THE RECT --------
  201.  
  202.         MOVE.W    #True,Result(A6)    ; we got the resource, return true
  203.         MOVEA.L    (A0),A0            ; pointer to RECT resource in A0
  204.         MOVEA.L    TheRect(A6),A1        ; pointer to the dest. RECT in A1
  205.         MOVE.L    topLeft(A0),topLeft(A1)    ; copy to the rect passed to us
  206.         MOVE.L    botRight(A0),botRight(A1)
  207.  
  208. Exit        UNLK    A6            ; destroy the link
  209.         MOVEA.L    (SP)+,A0        ; pull off the return address
  210.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  211.         JMP    (A0)            ; return to the caller
  212.  
  213.         DbgInfo    GetRect            ; this name will appear in the debugger
  214.         ENDF
  215.  
  216. * ================================================
  217. * FUNCTION IsDAWindow(window: WindowPtr): BOOLEAN;
  218. * ================================================
  219. * Check if a window belongs to a desk accessory.  DA window has a negitive kind.
  220.  
  221.         SEG    'Main'
  222. IsDAWindow    FUNC    EXPORT            ; any source file can use this routine
  223.  
  224. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  225. Result        DS.W    1            ; function's result returned to caller
  226. ParamBegin    EQU    *            ; start parameters after this point
  227. TheWindow    DS.L    1            ; a window's pointer passed by caller
  228. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  229. RetAddr     DS.L    1            ; place holder for return address
  230. A6Link        DS.L    1            ; place holder for A6 link
  231. LocalSize    EQU     *            ; size of all the local variables
  232.         ENDR
  233.  
  234.         WITH    StackFrame        ; cover our local stack frame
  235.         LINK    A6,#LocalSize        ; allocate our local stack frame
  236.  
  237.         MOVE.W    #False,Result(A6)    ; first, initialize the result
  238.         CMPI.L    #NIL,TheWindow(A6)    ; valid pointer?
  239.         BEQ.S    Exit            ; it was NIL, look out!
  240.  
  241.         MOVEA.L    TheWindow(A6),A0    ; get the window pointer
  242.         MOVE.W    WindowKind(A0),D0    ; what kind of window was it?
  243.         BPL.S    Exit            ; DA windows are negitive
  244.  
  245.         MOVE.W    #True,Result(A6)    ; return true to the caller
  246. Exit        UNLK    A6            ; destroy the link
  247.         MOVEA.L    (SP)+,A0        ; pull off the return address
  248.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  249.         JMP    (A0)            ; return to the caller
  250.  
  251.         DbgInfo    IsDAWind        ; this name will appear in the debugger
  252.         ENDF
  253.  
  254. * ================================================
  255. * FUNCTION IsAppWindow(window: WindowPtr): BOOLEAN;
  256. * ================================================
  257. * Check to see if a window belongs to the application. If the window pointer
  258. * passed was NIL, then it could not be an application window. WindowKinds
  259. * that are negative belong to the system and windowKinds less than userKind
  260. * are reserved by Apple except for windowKinds equal to dialogKind, which
  261. * means it is a dialog.
  262. * In order to reduce the chance of accidentally treating some window
  263. * as an AppWindow that shouldn't be, we'll only return true if the windowkind
  264. * is userKind. If you add different kinds of windows to Sample you'll need
  265. * to change how this all works.
  266.  
  267.         SEG    'Main'
  268. IsAppWindow    FUNC    EXPORT            ; any source file can use this routine
  269.  
  270. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  271. Result        DS.W    1            ; function's result returned to caller
  272. ParamBegin    EQU    *            ; start parameters after this point
  273. TheWindow    DS.L    1            ; a window's pointer passed by caller
  274. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  275. RetAddr     DS.L    1            ; place holder for return address
  276. A6Link        DS.L    1            ; place holder for A6 link
  277. LocalSize    EQU     *            ; size of all the local variables
  278.         ENDR
  279.  
  280.         WITH    StackFrame        ; cover our local stack frame
  281.         LINK    A6,#LocalSize        ; allocate our local stack frame
  282.  
  283.         MOVE.W    #False,Result(A6)    ; first, initialize the result
  284.         CMPI.L    #NIL,TheWindow(A6)    ; valid pointer?
  285.         BEQ.S    Exit            ; it was NIL, look out!
  286.  
  287.         MOVEA.L    TheWindow(A6),A0    ; get the window pointer
  288.         MOVE.W    WindowKind(A0),D0    ; what kind of window was it?
  289.         CMPI.W    #UserKind,D0        ; was it an application window?
  290.         BNE.S    Exit            ; no, result is going to be false
  291.  
  292.         MOVE.W    #True,Result(A6)    ; return true to the caller
  293.  
  294. Exit        UNLK    A6            ; destroy the link
  295.         MOVEA.L    (SP)+,A0        ; pull off the return address
  296.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  297.         JMP    (A0)            ; return to the caller
  298.  
  299.         DbgInfo    IsAppWin        ; this name will appear in the debugger
  300.         ENDF
  301.  
  302. * ================================================
  303. * PROCEDURE AlertUser;
  304. * ================================================
  305. * Display an alert that tells the user an error occurred, then exit the program.
  306. * This routine is used as an ultimate bail-out for serious errors that prohibit
  307. * the continuation of the application. Errors that do not require the termination
  308. * of the application should be handled in a different manner. Error checking and
  309. * reporting has a place even in the simplest application. For simplicity, the alert
  310. * displayed here only says that an error occurred, but not what it was. There are
  311. * various methods available for being more specific.
  312.  
  313.         SEG    'Main'        ; case sensitive
  314. AlertUser    PROC    EXPORT            ; any source file can use this routine
  315.  
  316. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  317. ParamBegin    EQU    *            ; start parameters after this point
  318. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  319. RetAddr     DS.L    1            ; place holder for return address
  320. A6Link        DS.L    1            ; place holder for A6 link
  321. LocalSize    EQU     *            ; size of all the local variables
  322.         ENDR
  323.  
  324.         WITH    StackFrame        ; cover our local stack frame
  325.         LINK    A6,#LocalSize        ; allocate our local stack frame
  326.  
  327.         CLR.W    -(SP)            ; space for result of Alert
  328.         MOVE.W    #rUserAlert,-(SP)    ; resource for alert dialog
  329.         CLR.L    -(SP)            ; no filter procedure used here
  330.         _Alert                ; read the resource and display it
  331.         MOVE.W    (SP)+,D0        ; I don't care which item is was
  332.         _ExitToShell            ; we're out of here, no error recovery
  333.  
  334. Exit        UNLK    A6            ; destroy the link
  335.         MOVEA.L    (SP)+,A0        ; pull off the return address
  336.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  337.         JMP    (A0)            ; return to the caller
  338.  
  339.         DbgInfo    AlrtUser        ; this name will appear in the debugger
  340.         ENDP
  341.  
  342. * ================================================
  343. * FUNCTION DoCloseWindow(window: WindowPtr) : BOOLEAN;
  344. * ================================================
  345. * At this point, if there was a document associated with a window, you could
  346. * do any document saving processing if it is 'dirty'.  DoCloseWindow would
  347. * return TRUE if the window actually closes, i.e., the user does not cancel
  348. * from a save dialog. This result is handy when the user quits an application,
  349. * but then cancels a save of a document associated with a window. We also added
  350. * code to close the application window since otherwise, the termination routines
  351. * would never stop looping, waiting for FrontWindow to return NIL.
  352.  
  353.          SEG    'Main'            ; case sensitive
  354. DoCloseWindow    FUNC    EXPORT            ; any source file can use this routine
  355.  
  356. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  357. Result        DS.W    1            ; function's result returned to caller
  358. ParamBegin    EQU    *            ; start parameters after this point
  359. WindowPtr    DS.L    1            ; passed window pointer parameter
  360. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  361. RetAddr     DS.L    1            ; place holder for return address
  362. A6Link        DS.L    1            ; place holder for A6 link
  363. LocalSize    EQU     *            ; size of all the local variables
  364.         ENDR
  365.  
  366.         WITH    StackFrame        ; cover our local stack frame
  367.         LINK    A6,#LocalSize        ; allocate our local stack frame
  368.  
  369.         MOVE.W    #True,Result(A6);    ; initialize the function's result
  370.  
  371.         CLR.W    -(SP)            ; space for result of IsDAWindow
  372.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  373.         BSR    IsDAWindow
  374.         MOVE.W    (SP)+,D0        ; result of IsDAWindow
  375.         CMPI.W    #True,D0
  376.         BNE.S    @1            ; this wasn't a DA window
  377.  
  378.         MOVEA.L    WindowPtr(A6),A0    ; get window pointer
  379.         MOVE.W    WindowKind(A0),-(SP)    ; pass the refNum of DA
  380.         _CloseDeskAcc
  381.         BRA.S    Exit            ; all done
  382.  
  383. @1        CLR.W    -(SP)            ; space for result of IsAppWindow
  384.         MOVE.L    WindowPtr(A6),-(SP)    ; pass a the window pointer
  385.         BSR    IsAppWindow
  386.         MOVE.W    (SP)+,D0        ; result of IsAppWindow
  387.         CMPI.W    #True,D0
  388.         BNE.S    Exit            ; it wasn't our application's window
  389.  
  390.         MOVE.L    WindowPtr(A6),-(SP)    ; close window, it shouldn't be a dialog
  391.         _CloseWindow            ; close the application window
  392.  
  393. Exit        UNLK    A6            ; destroy the link
  394.         MOVEA.L    (SP)+,A0        ; pull off the return address
  395.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  396.         JMP    (A0)            ; return to the caller
  397.  
  398.         DbgInfo    ClosWind        ; this name will appear in the debugger
  399.         ENDF
  400.  
  401. * ================================================
  402. * PROCEDURE Terminate;
  403. * ================================================
  404. * Clean up the application and exit. We close all of the windows so that
  405. * they can update their documents, if any.  We don't have much to do here.
  406. * Just close our windows and then exit.  If we find out that a Cancel has
  407. * occurred (DoCloseWindow will return False) we won't exit to the shell,
  408. * but will simply exit this procedure.
  409.  
  410.         SEG    'Main'            ; case sensitive
  411. Terminate    PROC    EXPORT
  412.  
  413. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  414. ParamBegin    EQU    *            ; start parameters after this point
  415. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  416. RetAddr     DS.L    1            ; place holder for return address
  417. A6Link        DS.L    1            ; place holder for A6 link
  418. WindowPtr    DS.L    1            ; local variable for a window pointer
  419. Closed        DS.W    1            ; local variable for looping
  420. LocalSize    EQU     *            ; size of all the local variables
  421.         ENDR
  422.  
  423.         IMPORT    DoCloseWindow
  424.  
  425.         WITH    StackFrame        ; cover our local stack frame
  426.         LINK    A6,#LocalSize        ; allocate our local stack frame
  427.  
  428.         MOVE.W    #True,Closed(A6)    ; initialize local variable
  429.  
  430. Loop        CLR.L    -(SP)            ; space for front window pointer
  431.         _FrontWindow
  432.         MOVE.L    (SP)+,WindowPtr(A6)    ; get the front window pointer
  433.         CMPI.L    #NIL,WindowPtr(A6)    ; is there a front window?
  434.         BEQ.S    @1            ; there are no more windows
  435.  
  436.         CLR.W    -(SP)            ; space for result of DoCloseWindow
  437.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  438.         BSR    DoCloseWindow        ; close all our windows
  439.         MOVE.W    (SP)+,Closed(A6)    ; get result of DoCloseWindow
  440.         CMPI.W    #True,Closed(A6)    ; what's the result of DoCloseWindow?
  441.         BNE.S    Exit            ; user didn't want to close that window
  442.  
  443.         BRA.S    Loop            ; loop again and close the next window
  444.  
  445. @1        CMPI.W    #True,Closed(A6)    ; should we really terminate?
  446.         BNE.S    Exit            ; no, exit this procedure
  447.  
  448.         _ExitToShell            ; we're done, let's get out of here
  449.  
  450. Exit        UNLK    A6            ; destroy the link
  451.         MOVEA.L    (SP)+,A0        ; pull off the return address
  452.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  453.         JMP    (A0)            ; return to the caller
  454.  
  455.         DbgInfo    Terminat        ; this name will appear in the debugger
  456.         ENDP
  457.  
  458. * ================================================
  459. * PROCEDURE SetLight(window: WindowPtr; newStopped: BOOLEAN);
  460. * ================================================
  461. * Change the setting of the light and force an update event.
  462. * newStopped is the state of the stop light the user is requesting.
  463.  
  464.         SEG    'Main'            ; case sensitive
  465. SetLight    PROC    EXPORT            ; any source file can use this routine
  466.  
  467. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  468. ParamBegin    EQU    *            ; start parameters after this point
  469. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  470. newStopped    DS.W    1            ; test value passed by caller
  471. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  472. RetAddr     DS.L    1            ; place holder for return address
  473. A6Link        DS.L    1            ; place holder for A6 link
  474. LocalSize    EQU     *            ; size of all the local variables
  475.         ENDR
  476.  
  477.         WITH    StackFrame        ; cover our local stack frame
  478.         LINK    A6,#LocalSize        ; allocate our local stack frame
  479.  
  480.         MOVE.W    G.Stopped,D0        ; get state of stop light
  481.         CMP.W    newStopped(A6),D0    ; compare to the new state
  482.         BEQ.S    Exit            ; they're the same, stupid user!
  483.  
  484.         MOVE.W    newStopped(A6),G.Stopped ; set global to the new state
  485.         MOVE.L    WindowPtr(A6),-(SP)
  486.         _SetPort            ; set the port to us
  487.         MOVEA.L    WindowPtr(A6),A0    ; force update event for window
  488.         PEA    portRect(A0)        ; invalidate entire window
  489.         _InvalRect
  490.  
  491. Exit        UNLK    A6            ; destroy the link
  492.         MOVEA.L    (SP)+,A0        ; pull off the return address
  493.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  494.         JMP    (A0)            ; return to the caller
  495.  
  496.         DbgInfo    SetLight        ; this name will appear in the debugger
  497.         ENDP
  498.  
  499. * ================================================
  500. * PROCEDURE AdjustMenus;
  501. * ================================================
  502. * Enable and disable menus based on the current state.  The user can only select
  503. * enabled menu items. We set up all the menu items before calling MenuSelect or
  504. * MenuKey, since these are the only times that a menu item can be selected. Note
  505. * that MenuSelect is also the only time the user will see menu items. This
  506. * approach to deciding what enable/disable state a menu item has the advantage
  507. * of concentrating all the decision making in one routine, as opposed to being
  508. * spread throughout the application.  Other application designs may take a
  509. * different approach that are just as valid.
  510.  
  511.         SEG    'Main'            ; case sensitive
  512. AdjustMenus    PROC    EXPORT            ; any source file can use this routine
  513.  
  514. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  515. ParamBegin    EQU    *            ; start parameters after this point
  516. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  517. RetAddr     DS.L    1            ; place holder for return address
  518. A6Link        DS.L    1            ; place holder for A6 link
  519. FrontMost    DS.L    1            ; local copy of the front window
  520. Menu        DS.L    1            ; local copy of the menu handle
  521. LocalSize    EQU     *            ; size of all the local variables
  522.         ENDR
  523.  
  524.         WITH    StackFrame        ; cover our local stack frame
  525.         LINK    A6,#LocalSize        ; allocate our local stack frame
  526.  
  527.         CLR.L    -(SP)            ; space for result
  528.         _FrontWindow
  529.         MOVE.L    (SP)+,FrontMost(A6)    ; save the front window
  530.  
  531. * ------------- ADJUST THE FILE MENU -------------
  532. AdjustFile
  533.         CLR.L    -(SP)            ; space for result
  534.         MOVE.W    #FileMenu,-(SP)        ; get the File menu handle
  535.         _GetMHandle
  536.         MOVE.L    (SP)+,Menu(A6)        ; save the menu handle
  537.         CLR.W    -(SP)            ; space for result
  538.         MOVE.L    FrontMost(A6),-(SP)
  539.         BSR    IsDAWindow
  540.         MOVE.W    (SP)+,D0        ; get the result of the function
  541.         CMPI.W    #True,D0        ; was it the DA window?
  542.         BNE.S    @1            ; no, then disable the close item
  543.  
  544.         MOVE.L    Menu(A6),-(SP)        ; it was an application window
  545.         MOVE.W    #CloseItem,-(SP)
  546.         _EnableItem            ; enable the close for DAs only
  547.         BRA.S    AdjustEdit
  548.  
  549. @1        MOVE.L    Menu(A6),-(SP)        ; it was not a DA window
  550.         MOVE.W    #CloseItem,-(SP)
  551.         _DisableItem            ; disable close for all others
  552.  
  553. * ------------- ADJUST THE EDIT MENU -------------
  554. AdjustEdit
  555.         CLR.L    -(SP)            ; space for result
  556.         MOVE.W    #EditMenu,-(SP)        ; get the Edit menu handle
  557.         _GetMHandle
  558.         MOVE.L    (SP)+,Menu(A6)        ; save the menu handle
  559.         CLR.W    -(SP)            ; space for result
  560.         MOVE.L    FrontMost(A6),-(SP)
  561.         BSR    IsDAWindow
  562.         MOVE.W    (SP)+,D0        ; get the result of the function
  563.         CMPI.W    #True,D0        ; was it the DA window?
  564.         BNE.S    @2            ; no, disable the edit menu
  565.  
  566.         MOVE.L    Menu(A6),-(SP)        ; it was for a DA window
  567.         MOVE.W    #CutItem,-(SP)
  568.         _EnableItem            ; enable the Cut
  569.         MOVE.L    Menu(A6),-(SP)
  570.         MOVE.W    #CopyItem,-(SP)
  571.         _EnableItem            ; enable the Copy
  572.         MOVE.L    Menu(A6),-(SP)
  573.         MOVE.W    #PasteItem,-(SP)
  574.         _EnableItem            ; enable the Paste
  575.         MOVE.L    Menu(A6),-(SP)
  576.         MOVE.W    #ClearItem,-(SP)
  577.         _EnableItem            ; enable the Clear
  578.         BRA.S    AdjustLight        ; done with the edit menu
  579.  
  580. @2        MOVE.L    Menu(A6),-(SP)        ; disable the edit menu
  581.         MOVE.W    #UndoItem,-(SP)
  582.         _DisableItem            ; disable the Undo
  583.         MOVE.L    Menu(A6),-(SP)
  584.         MOVE.W    #CutItem,-(SP)
  585.         _DisableItem            ; disable the Cut
  586.         MOVE.L    Menu(A6),-(SP)
  587.         MOVE.W    #CopyItem,-(SP)
  588.         _DisableItem            ; disable the Copy
  589.         MOVE.L    Menu(A6),-(SP)
  590.         MOVE.W    #PasteItem,-(SP)
  591.         _DisableItem            ; disable the Paste
  592.         MOVE.L    Menu(A6),-(SP)
  593.         MOVE.W    #ClearItem,-(SP)
  594.         _DisableItem            ; disable the Clear
  595.  
  596. * ------------- ADJUST THE LIGHT MENU -------------
  597. AdjustLight
  598.         CLR.L    -(SP)            ; space for result
  599.         MOVE.W    #LightMenu,-(SP)    ; get the Edit menu handle
  600.         _GetMHandle
  601.         MOVE.L    (SP)+,Menu(A6)        ; save the menu handle
  602.         CLR.W    -(SP)            ; space for result
  603.         MOVE.L    FrontMost(A6),-(SP)    ; the front window
  604.         BSR    IsAppWindow
  605.         MOVE.W    (SP)+,D3        ; save the result of the function
  606.         CMPI.W    #True,D3        ; was our window in front?
  607.         BNE.S    @3            ; no, disable the menu items
  608.  
  609.         MOVE.L    Menu(A6),-(SP)        ; enable the light menu
  610.         MOVE.W    #StopItem,-(SP)
  611.         _EnableItem            ; enable the stop
  612.         MOVE.L    Menu(A6),-(SP)
  613.         MOVE.W    #GoItem,-(SP)
  614.         _EnableItem            ; enable the go for our window
  615.         BRA.S    @4            ; now check the menu items
  616.  
  617. @3        MOVE.L    Menu(A6),-(SP)        ; disable the light menu
  618.         MOVE.W    #StopItem,-(SP)
  619.         _DisableItem            ; disable the stop
  620.         MOVE.L    Menu(A6),-(SP)
  621.         MOVE.W    #GoItem,-(SP)
  622.         _DisableItem            ; disable the go
  623.         BRA.S    Exit            ; nothing to check, get out of here
  624.  
  625. @4        MOVE.W    G.Stopped,D0        ; get the current state of the light
  626.         CMPI.W    #True,D0        ; is the stop light on?
  627.         BNE.S    @5            ; no, the green light is on
  628.  
  629.         MOVE.L    Menu(A6),-(SP)        ; set menu to red light = on
  630.         MOVE.W    #StopItem,-(SP)
  631.         MOVE.W    #True,-(SP)
  632.         _CheckItem            ; check the StopItem in the menu
  633.         MOVE.L    Menu(A6),-(SP)
  634.         MOVE.W    #GoItem,-(SP)
  635.         MOVE.W    #False,-(SP)
  636.         _CheckItem            ; un-check the GoItem in the menu
  637.         BRA.S    Exit            ; now we're done, get out of here
  638.  
  639. @5        MOVE.L    Menu(A6),-(SP)        ; set menu to green light = on
  640.         MOVE.W    #StopItem,-(SP)
  641.         MOVE.W    #False,-(SP)
  642.         _CheckItem            ; un-check the StopItem in the menu
  643.         MOVE.L    Menu(A6),-(SP)
  644.         MOVE.W    #GoItem,-(SP)
  645.         MOVE.W    #True,-(SP)
  646.         _CheckItem            ; check the GoItem in the menu
  647.  
  648. Exit        UNLK    A6            ; destroy the link
  649.         MOVEA.L    (SP)+,A0        ; pull off the return address
  650.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  651.         JMP    (A0)            ; return to the caller
  652.  
  653.         DbgInfo    AdjstMnu        ; this name will appear in the debugger
  654.         ENDP
  655.  
  656. * ================================================
  657. * PROCEDURE DrawWindow(window: WindowPtr);
  658. * ================================================
  659. * Draw the contents of the application's window. We do some drawing in color,
  660. * using Classic QuickDraw's color capabilities. This will be black and white on
  661. * old machines, but color on color machines. The window's visRgn has been set by
  662. * the Update routine to cause drawing only where it needs to be done.
  663.  
  664.         SEG    'Main'            ; case sensitive
  665. DrawWindow    PROC    EXPORT            ; any source file can use this routine
  666.  
  667. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  668. ParamBegin    EQU    *            ; start parameters after this point
  669. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  670. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  671. RetAddr     DS.L    1            ; place holder for return address
  672. A6Link        DS.L    1            ; place holder for A6 link
  673. LocalSize    EQU     *            ; size of all the local variables
  674.         ENDR
  675.  
  676.         WITH    StackFrame        ; cover our local stack frame
  677.         LINK    A6,#LocalSize        ; allocate our local stack frame
  678.  
  679.         MOVE.L    WindowPtr(A6),-(SP)
  680.         _SetPort            ; set the current port to us
  681.         MOVEA.L    WindowPtr(A6),A0    ; erase the entire window
  682.         PEA    portRect(A0)        ; the window's rect
  683.         _EraseRect            ; clear out anything remaining
  684.         MOVE.W    G.Stopped,D0        ; find the state of the lights
  685.         CMPI.W    #True,D0
  686.         BNE.S    @1            ; red light should be off
  687.  
  688. * ------------- RED LIGHT -------------
  689.  
  690.         MOVE.L    #redColor,-(SP)        ; make the red light go on
  691.         _ForeColor
  692.         PEA    G.StopRect
  693.         _PaintOval
  694.         MOVE.L    #whiteColor,-(SP)    ; make the green light go off
  695.         _ForeColor
  696.         PEA    G.GoRect
  697.         _PaintOval
  698.         BRA.S    @2
  699.  
  700. * ------------- GREEN LIGHT -------------
  701.  
  702. @1        MOVE.L    #greenColor,-(SP)    ; make the green light go on
  703.         _ForeColor
  704.         PEA    G.GoRect
  705.         _PaintOval
  706.         MOVE.L    #whiteColor,-(SP)    ; make the red light go off
  707.         _ForeColor
  708.         PEA    G.StopRect
  709.         _PaintOval
  710.  
  711. * ------------- FRAME THE LIGHTS -------------
  712.  
  713. @2        MOVE.L    #blackColor,-(SP)
  714.         _ForeColor
  715.         PEA    G.StopRect
  716.         _FrameOval            ; draw black line around light
  717.         PEA    G.GoRect
  718.         _FrameOval            ; draw black line around light
  719.  
  720. Exit        UNLK    A6            ; destroy the link
  721.         MOVEA.L    (SP)+,A0        ; pull off the return address
  722.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  723.         JMP    (A0)            ; return to the caller
  724.  
  725.         DbgInfo    DrawWind        ; this name will appear in the debugger
  726.         ENDP
  727.  
  728. * ================================================
  729. * PROCEDURE GetGlobalMouse(VAR mouse: Point);
  730. * ================================================
  731. * Get the global coordinates of the mouse. When you call OSEventAvail
  732. * it will return either a pending event or a null event. In either case,
  733. * the where field of the event record will contain the current position
  734. * of the mouse in global coordinates and the modifiers field will reflect
  735. * the current state of the modifiers. Another way to get the global
  736. * coordinates is to call GetMouse and LocalToGlobal, but that requires
  737. * being sure that thePort is set to a valid port.}
  738.  
  739.         SEG    'Main'            ; case sensitive
  740. GetGlobalMouse    PROC    EXPORT            ; any source file can use this routine
  741.  
  742. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  743. ParamBegin    EQU    *            ; start parameters after this point
  744. Mouse        DS.L    1            ; passed reference to mouse position
  745. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  746. RetAddr     DS.L    1            ; place holder for return address
  747. A6Link        DS.L    1            ; place holder for A6 link
  748. TheEvent     DS    EventRecord         ; local copy of the event record
  749. LocalSize    EQU     *            ; size of all the local variables
  750.         ENDR
  751.  
  752.         WITH    StackFrame        ; cover our local stack frame
  753.         LINK    A6,#LocalSize        ; allocate our local stack frame
  754.  
  755.         MOVE.W    #NoEvents,D0        ; we aren't interested in any events
  756.         LEA    TheEvent(A6),A0        ; point to event record
  757.         _OSEventAvail            ; just the mouse position
  758.         MOVE.L    Mouse(A6),A0        ; deref address of mouse
  759.         MOVE.L    TheEvent.Where(A6),(A0)    ; stuff new value
  760.  
  761.         UNLK    A6            ; destroy the link
  762.         MOVEA.L    (SP)+,A0        ; pull off the return address
  763.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  764.         JMP    (A0)            ; return to the caller
  765.  
  766.         DbgInfo    GetGlobalMouse        ; this name will appear in the debugger
  767.         ENDP
  768.  
  769. * ================================================
  770. * PROCEDURE AdjustCursor(mouse: Point; region: RgnHandle);
  771. * ================================================
  772. * Change the cursor's shape, depending on its position. This also calculates the
  773. * region where the current cursor resides (for WaitNextEvent). If the mouse is
  774. * ever outside of that region, an event would be generated, causing this routine
  775. * to be called, allowing us to change the region to the region the mouse is
  776. * currently in. If there is more to the event than just the mouse moved, we
  777. * get called before the event is processed to make sure the cursor is the right
  778. * one. In any (ahem) event, this is called again before we fall back into WNE.
  779. * 1.02 - Removed the mouse position parameter and instead use the current position
  780. * of the mouse by calling GetMouse and LocalToGlobal.
  781.  
  782.         SEG    'Main'            ; case sensitive
  783. AdjustCursor    PROC    EXPORT
  784.  
  785. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  786. ParamBegin    EQU    *            ; start parameters after this point
  787. Where        DS.L    1            ; the mouse location passed to us
  788. MouseRegion    DS.L    1            ; passed pointer to current region
  789. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  790. RetAddr     DS.L    1            ; place holder for return address
  791. A6Link        DS.L    1            ; place holder for A6 link
  792. FrontMost    DS.L    1            ; local pointer to the front window
  793. ArrowRgn    DS.L    1            ; local handle to the arrow cursor region
  794. PlusRgn        DS.L    1            ; local handle to the plus cursor region
  795. LocalSize    EQU     *            ; size of all the local variables
  796.         ENDR
  797.  
  798.         IMPORT    IsDAWindow,IsAppWindow
  799.  
  800.         WITH    StackFrame        ; cover our local stack frame
  801.         LINK    A6,#LocalSize        ; allocate our local stack frame
  802.  
  803.         CLR.W    -(SP)            ; space for result of IsAppWindow
  804.         CLR.L    -(SP)            ; space for result of FrontWindow
  805.         _FrontWindow            ; push front window pointer
  806.         MOVE.L    (SP),FrontMost(A6)    ; copy pointer and keep it on stack
  807.         BSR    IsDAWindow        ; is this an application window?
  808.         MOVE.W    (SP)+,D0
  809.         CMPI.W    #True,D0
  810.         BEQ.W    Exit            ; not our window, don't adjust the cursor
  811.         CMPI.W    #True,G.InBackground
  812.         BEQ.W    Exit            ; and do nothing if we're in the background
  813.  
  814. * ------------- INITIALIZE SOME REGION DATA -------------
  815.  
  816.         CLR.L    -(SP)
  817.         _NewRgn                ; create an empty plus region
  818.         MOVE.L    (SP)+,PlusRgn(A6)
  819.         CLR.L    -(SP)
  820.         _NewRgn                ; create an empty arrow region
  821.         MOVE.L    (SP)+,ArrowRgn(A6)
  822.         MOVE.L    ArrowRgn(A6),-(SP)    ; arrow region handle
  823.         MOVE.W    #ExtremeNeg,-(SP)    ; big left corner
  824.         MOVE.W    #ExtremeNeg,-(SP)    ; big top corner
  825.         MOVE.W    #ExtremePos,-(SP)    ; big right corner
  826.         MOVE.W    #ExtremePos,-(SP)    ; big bottom corner
  827.         _SetRecRgn            ; really big rectangular region
  828.  
  829.         CLR.W    -(SP)
  830.         MOVE.L    FrontMost(A6),-(SP)
  831.         BSR    IsAppWindow        ; is this an application window?
  832.         MOVE.W    (SP)+,D0
  833.         CMPI.W    #True,D0
  834.         BNE.S    @1            ; our window isn't in front?
  835.  
  836. * ------------- CALCULATE THE PLUS REGION -------------
  837.  
  838.         MOVE.L    FrontMost(A6),-(SP)
  839.         _SetPort            ; set the current port to us
  840.         MOVEA.L    FrontMost(A6),A0
  841.         MOVE.W    portBits+bounds+left(A0),D0
  842.         NEG.W    D0            ; offset window's left edge...
  843.         MOVE.W    D0,-(SP)        ; to the screen's left edge
  844.         MOVEA.L    FrontMost(A6),A0
  845.         MOVE.W    portBits+bounds+top(A0),D0
  846.         NEG.W    D0            ; offset window's top edge...
  847.         MOVE.W    D0,-(SP)        ; to the screen's top edge
  848.         _SetOrigin            ; make window rect global
  849.         MOVE.L    PlusRgn(A6),-(SP)    ; handle to empty plus region
  850.         MOVEA.L    FrontMost(A6),A0    ; pointer to our window
  851.         PEA    portRect(A0)        ; window rect's global coordinates
  852.         _RectRgn            ; make global window rect into region
  853.         MOVE.L    PlusRgn(A6),-(SP)    ; get intersection of plus and window region
  854.         MOVEA.L    FrontMost(A6),A0
  855.         MOVE.L    visRgn(A0),-(SP)    ; get front window's visRgn
  856.         MOVE.L    PlusRgn(A6),-(SP)    ; resulting region will be in PlusRgn
  857.         _SectRgn            ; intersection the two regions
  858.         CLR.L    -(SP)            ; reset the origin of our window to 0,0
  859.         _SetOrigin
  860.  
  861. @1        MOVE.L    ArrowRgn(A6),-(SP)    ; the really big rectangular region
  862.         MOVE.L    PlusRgn(A6),-(SP)    ; the region of our window
  863.         MOVE.L    ArrowRgn(A6),-(SP)    ; intersetion of the Arrow and Plus region
  864.         _DiffRgn            ; this is the region where the Arrow shows
  865.         CLR.W    -(SP)            ; space for result of PtInRect
  866.         MOVE.L    Where(A6),-(SP)        ; here's the mouse
  867.         MOVE.L    PlusRgn(A6),-(SP)    ; where the arrow should show up
  868.         _PtInRgn            ; was cursor in the arrow region?
  869.         MOVE.W    (SP)+,D0
  870.         CMPI.W    #True,D0
  871.         BNE.S    @2            ; cursor was in arrow region
  872.  
  873. * ------------- SET THE CURSOR AND NEW MOUSE REGION -------------
  874.  
  875.         CLR.L    -(SP)            ; space for result
  876.         MOVE.W    #plusCursor,-(SP)    ; I want the plus cursor now!
  877.         _GetCursor
  878.         MOVEA.L    (SP)+,A0        ; get the handle
  879.         CMPA.L    #NIL,A0
  880.         BEQ.S    Exit            ; check for NIL like a good boy
  881.         MOVE.L    (A0),-(SP)        ; got the plus cursor
  882.         _SetCursor            ; set cursor to plus
  883.         MOVE.L    PlusRgn(A6),-(SP)    ; current region containing cursor
  884.         MOVE.L    MouseRegion(A6),-(SP)    ; set it to the new region
  885.         _CopyRgn
  886.         BRA.S    @3            ; we're done, get out of here
  887.  
  888. @2        PEA    QD.Arrow        ; got arrow cursor at InitGraf
  889.         _SetCursor            ; set cursor to the Arrow
  890.         MOVE.L    ArrowRgn(A6),-(SP)    ; current region containing cursor
  891.         MOVE.L    MouseRegion(A6),-(SP)    ; set it to the new region
  892.         _CopyRgn
  893.  
  894. @3        MOVE.L    PlusRgn(A6),-(SP)    ; dispose of our two temporary regions
  895.         _DisposRgn
  896.         MOVE.L    ArrowRgn(A6),-(SP)
  897.         _DisposRgn
  898.  
  899. Exit        UNLK    A6            ; destroy the link
  900.         MOVEA.L    (SP)+,A0        ; pull off the return address
  901.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  902.         JMP    (A0)            ; return to the caller
  903.  
  904.         DbgInfo    AdjstCur        ; this name will appear in the debugger
  905.         ENDP
  906.  
  907.         END                ; end of this source file
  908.